package com.ict.ycwl.pathcalculate.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ict.ycwl.common.utils.StringUtils;
import com.ict.ycwl.common.web.AjaxResult;
import com.ict.ycwl.pathcalculate.common.exception.CarNumberException;
import com.ict.ycwl.pathcalculate.form.AddRouteFrom;
import com.ict.ycwl.pathcalculate.form.AdjustPointForm;
import com.ict.ycwl.pathcalculate.form.GetColourConvexHullFrom;
import com.ict.ycwl.pathcalculate.form.RouteDataForm;
import com.ict.ycwl.pathcalculate.mapper.AccumulationMapper;
import com.ict.ycwl.pathcalculate.mapper.GroupAreasMapper;
import com.ict.ycwl.pathcalculate.mapper.GroupMapper;
import com.ict.ycwl.pathcalculate.pojo.*;
import com.ict.ycwl.pathcalculate.service.CalculateService;
import com.ict.ycwl.pathcalculate.service.MapDisplayService;
import com.ict.ycwl.pathcalculate.service.RouteService;
import com.ict.ycwl.pathcalculate.vo.GroupRouteVO;
import com.ict.ycwl.pathcalculate.vo.TransitDepotRouteVO;
import com.ict.ycwl.pathcalculate.vo.RouteVO;
import com.ict.ycwl.pathcalculate.vo.details.AreaDetailsVO;
import com.ict.ycwl.pathcalculate.vo.RouteDataVO;
import com.ict.ycwl.pathcalculate.vo.details.StoreDetailsVO;
import io.swagger.annotations.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author yuhuaame
 */
@Api(tags = "路径计算API")
@Slf4j
@Validated
@RestController
@RequestMapping("/path")
@RequiredArgsConstructor
public class PathController {
    @Autowired
    private CalculateService calculateService;

    @Autowired
    private RouteService routeService;

    @Autowired
    private GroupMapper groupMapper;

    @Resource
    private GroupAreasMapper groupAreasMapper;

    @Resource
    private AccumulationMapper accumulationMapper;

    private final MapDisplayService mapDisplayService;


    @ApiOperation(value = "计算全部中转站接口")
    @GetMapping("/calculateAll")
    public Object calculateAll(@ApiParam(value = "调用api的Key", required = true)
                                     @RequestParam("apiKey") String apiKey) {
        List<ResultRoute> routes = null;
        try {
            routes = calculateService.calculateAll(apiKey);
        } catch (CarNumberException e) {
            return AjaxResult.error(e.getMessage());
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (routes.size() != 0) {
            return AjaxResult.success("操作成功", routes);
        } else {
            return AjaxResult.success("操作失败");
        }
    }

    @ApiOperation(value = "计算单个中转站接口")
    @GetMapping("/calculateOne")
    public Object calculateOne(@ApiParam(value = "计算的中转站的名字", required = true, example = "仁化")
                               @RequestParam("areaName") String areaName,
                               @ApiParam(value = "调用api的Key", required = true)
                               @RequestParam("apiKey") String apiKey,
                               @ApiParam(value = "计算的路线数量", required = true, example = "10")
                               @RequestParam("assignNumber") int assignNumber) {
        List<ResultRoute> routes = null;
        try {
            routes = calculateService.calculateOne(areaName, apiKey, assignNumber);
        } catch (CarNumberException e) {
            return AjaxResult.error(e.getMessage());
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (routes.size() != 0) {
            return AjaxResult.success("操作成功", routes);
        } else {
            return AjaxResult.success("操作失败");
        }
    }

    @ApiOperation(value = "获取地图所有班组分割线")
    @GetMapping("/getSplitLines")
    public Object getSplitLines(@ApiParam(value = "班组绕圈顺序", required = true, example = "二四五一三六")
                                @RequestParam("groupOrder") String groupOrder) {
        return AjaxResult.success(mapDisplayService.getSplitLines(groupOrder));
    }

//    @ApiOperation(value = "获取单个班组着色分块")
//    @PostMapping("/getColourConvexHull")
//    public Object getColourConvexHull(@Validated
//                                      @RequestBody GetColourConvexHullFrom requestParam) {
//        List<List<LngAndLat>> result = null;
//        try {
//            result = mapDisplayService.getColourConvexHull(requestParam);
//        } catch (IllegalArgumentException e) {
//            return AjaxResult.error("班组不存在");
//        }
//        return AjaxResult.success(result);
//    }

    @ApiOperation(value = "获取所有凸包打卡点")
    @GetMapping("/getConvexPoint")
    public Object getConvexPoint() {
        return AjaxResult.success(mapDisplayService.getConvexPoint());
    }

    @ApiOperation(value = "单条路径重新计算")
    @GetMapping("/calculateSingleRoute")
    public Object calculateSingleRoute(@ApiParam(value = "计算的路径的名字", required = true)
                                       @RequestParam("routeName") String routeName,
                                       @ApiParam(value = "调用api的Key", required = true)
                                       @RequestParam("apiKey") String apiKey) {
        List<ResultRoute> resultRoutes = calculateService.calculateSingleRoute(routeName, apiKey);
        if (resultRoutes.size() != 0) {
            return AjaxResult.success("操作成功", resultRoutes);
        } else {
            return AjaxResult.success("操作失败");
        }
    }


    /**
     * 获取路线详情，包含大区、路线、聚集区
     *
     * @return vo
     */
    @ApiOperation(value = "获取路线详情-大区路线聚集区信息")
    @GetMapping("/getRouteDetails")
    public AjaxResult getRouteDetails() {
        List<AreaDetailsVO> routeDetails = routeService.getRouteDetails();
        return AjaxResult.success(routeDetails);
    }

    /**
     * 获取聚集区下商户信息
     *
     * @return vo
     */
    @ApiOperation(value = "获取路线详情-聚集区下商户信息")
    @ApiParam(name = "accumulationId", value = "聚集区ID", example = "1749295912216735746", required = true)
    @GetMapping("/getStoreDetails/{accumulationId}")
    public AjaxResult getStoreDetails(@PathVariable String accumulationId) {
        List<StoreDetailsVO> storeDetails = routeService.getStoreDetails(Long.parseLong(accumulationId));
        return AjaxResult.success(storeDetails);
    }

    /**
     * 获取路线列表
     *
     * @return ar
     */
    /*@ApiOperation(value = "获取路线列表")
    @GetMapping("/getRouteList")
    public AjaxResult getRouteList() {
        List<RouteVO> routeList = routeService.getRouteList();
        return AjaxResult.success(routeList);
    }*/

    /**
     * 获取地图数据（外层）
     *
     * @return ar
     */
    @ApiOperation(value = "获取地图数据")
    @GetMapping("/getMapData")
    public AjaxResult getMapData() {
        List<RouteVO> mapData = routeService.getMapData();
        return AjaxResult.success(mapData);
    }

    /**
     * 获取中转站历史路径列表数据
     *
     * @return ar
     */
    @ApiOperation(value = "路径分析-获取中转站历史路径列表数据")
    @GetMapping("/getTransitDepotRouteData")
    public AjaxResult getAreaRouteData() {
        List<TransitDepotRouteVO> areaRouteData = routeService.getTransitDepotRouteData();
        return AjaxResult.success(areaRouteData);
    }

    /**
     * 获取路径详细数据
     *
     * @return ar
     */
    @ApiOperation(value = "路径分析-获取路径详细数据")
    @GetMapping("/getRouteData")
    public AjaxResult getRouteData(@Valid RouteDataForm form) {
        RouteDataVO routeData = routeService.getRouteData(form.getTransitDepotId(), form.getRouteName());
        if (routeData == null) {
            return AjaxResult.error("路径不存在，请重试");
        }
        return AjaxResult.success(routeData);
    }

    /**
     * 保存路径
     *
     * @return ar
     */
    @ApiOperation(value = "路径分析-保存路径")
    @PostMapping("/addRoute")
    public AjaxResult addRoute(@Validated @RequestBody List<AddRouteFrom> from) {
        try {
            String message = routeService.addRoute(from);
            if (StringUtils.isNotEmpty(message)) {
                return AjaxResult.error(message);
            }
        } catch (Exception e) {
            log.error(e.getMessage());
            return AjaxResult.error("参数有误，请重试");
        }
        return AjaxResult.success("操作成功");
    }

    /**
     * 获取路径版本号
     *
     * @param date
     * @param transitDepotId
     * @return
     */
    @ApiOperation(value = "路径分析-获取路径版本号")
    @GetMapping("/getRouteVersion")
    @ApiImplicitParams({
            @ApiImplicitParam(value = "日期", name = "date", type = "String", required = true, example = "2024-03-10"),
            @ApiImplicitParam(value = "中转站ID", name = "transitDepotId", type = "Long", required = true, example = "8")
    })
    public AjaxResult getRouteVersion(String date, Long transitDepotId) {
        List<String> routeVersion = routeService.getRouteVersion(date, transitDepotId);
        return AjaxResult.success(routeVersion);
    }


    /**
     * 路径比较-New
     *
     * @param routeIdList
     * @return
     */
    @ApiOperation(value = "路径比较")
    @GetMapping("/compare/{routeIdList}")
    @ApiParam(name = "routeIdList", value = "大区Id集合", type = "List<Long>", required = true)
    public AjaxResult compare(@PathVariable("routeIdList") List<Long> routeIdList) {
        List<RouteDataVO> list = new ArrayList<>();
        for (Long id : routeIdList) {
            Route route = routeService.getById(id);
            RouteDataVO routeDataVO = routeService.getRouteDataVO(route);
            list.add(routeDataVO);
        }
        return AjaxResult.success(list);
    }

    /**
     * 调整打卡点所属路径或大区
     *
     * @param adjustPointForm
     * @return
     */
    @ApiOperation("调整打卡点所属路径或大区")
    @PostMapping("/adjustPoint")
    public AjaxResult adjustPoint(@RequestBody AdjustPointForm adjustPointForm) {
        Long accumulationId = adjustPointForm.getAccumulationId();
        Long areaId = adjustPointForm.getAreaId();
        Long routeId = adjustPointForm.getRouteId();

        // 参数校验
        if (areaId == null && routeId == null) {
            return AjaxResult.error("参数有误");
        }
        // 修改
        Accumulation accumulation = new Accumulation();
        accumulation.setRouteId(routeId);
        accumulation.setAreaId(areaId);
        accumulation.setAccumulationId(accumulationId);
        accumulationMapper.updateById(accumulation);

        return AjaxResult.success("操作成功");
    }

    @ApiOperation("班组比较")
    @GetMapping("/compareBaseGroup/{groupIdList}")
    public AjaxResult compareBaseGroup(@PathVariable("groupIdList") Long[] groupIdList) {
        List<GroupRouteVO> result = new ArrayList<>();
        // 遍历班组Id集合，获取各自area集合
        for (Long groupId : groupIdList) {
            // 查询大区集合
            QueryWrapper<GroupAreas> gaQueryWrapper = new QueryWrapper<>();
            gaQueryWrapper.eq("group_id", groupId);
            List<GroupAreas> groupAreas = groupAreasMapper.selectList(gaQueryWrapper);
            List<Long> areaIdList = groupAreas.stream().map(GroupAreas::getAreaId).collect(Collectors.toList());

            // 本班组累积数据
            BigDecimal totalDistance = new BigDecimal("0");
            BigDecimal totalWorkTime = new BigDecimal("0");
            BigDecimal totalCargoWeight = new BigDecimal("0");

            int routeSize = 0;
            for (Long areaId : areaIdList) {
                // 获取大区下所有路线
                QueryWrapper<Route> queryWrapper = new QueryWrapper<>();
                queryWrapper.eq("area_id", areaId);
                queryWrapper.eq("is_delete", 0);
                List<Route> routeList = routeService.list(queryWrapper);
                // 获取每个路线数据
                for (Route route : routeList) {
                    RouteDataVO routeDataVO = routeService.getRouteDataVO(route);
                    // 计算大区下所有路线数据累积
                    BigDecimal routeDistance = new BigDecimal(routeDataVO.getDistance());
                    totalDistance = totalDistance.add(routeDistance);
                    totalWorkTime = totalWorkTime.add(new BigDecimal(routeDataVO.getWorkTime()));
                    BigDecimal routeCargoWeight = new BigDecimal(routeDataVO.getCargoWeight());
                    totalCargoWeight = totalCargoWeight.add(routeCargoWeight);
                    routeSize++;
                }

            }
            if (routeSize == 0) {
                result.add(new GroupRouteVO());
                continue;
            }
            BigDecimal size = new BigDecimal(routeSize);
            BigDecimal averageWorkTime = totalWorkTime.divide(size, 2, RoundingMode.HALF_UP);
            BigDecimal averCargoWeight = totalCargoWeight.divide(size, 2, RoundingMode.HALF_UP);
            BigDecimal averageDistance = (totalDistance.divide(size, 2, RoundingMode.HALF_UP)).divide(BigDecimal.valueOf(1000), 2, RoundingMode.HALF_UP);

            // 获取groupName
            String groupName = groupMapper.selectById(groupId).getGroupName();

            GroupRouteVO groupRouteVO = GroupRouteVO.builder().groupId(groupId).groupName(groupName)
                    .averageWorkTime(averageWorkTime.toString())
                    .averCargoWeight(averCargoWeight.toString())
                    .averageDistance(averageDistance.toString())
                    .totalCargoWeight(totalCargoWeight.toString()).build();
            result.add(groupRouteVO);

        }
        // 返回
        return AjaxResult.success(result);

    }

}
